/**
 * @file cdnet.c
 * @brief CDNET协议实现 - Layer 0和Layer 1
 * @details CDNET协议栈的核心实现文件，提供Layer 0和Layer 1的协议处理功能
 *          Layer 0：8位端口寻址
 *          Layer 1：16位端口寻址
 * 
 * @author 原作者：Duke Fong <d@d-l.io>
 * @author 修改团队：mastwet@Undefine Innovation
 * @date 2024
 * @copyright MIT License
 */

#include "cdnet.h"
#include "modbus_crc.h"
#include <string.h>

/**
 * @brief 初始化CDNET协议实例
 * @param cdnet CDNET实例指针
 * @param address 本节点地址（0-254）
 * @details 初始化CDNET协议栈，包括CDBUS底层协议
 */
void cdnet_init(cdnet_t *cdnet, uint8_t address) {
    memset(cdnet, 0, sizeof(cdnet_t));
    cdbus_init(&cdnet->cdbus, address);
}

/**
 * @brief 设置地址过滤器
 * @param cdnet CDNET实例指针
 * @param filter 过滤器地址
 * @details 设置CDBUS层的地址过滤器
 */
void cdnet_set_filter(cdnet_t *cdnet, uint8_t filter) {
    cdbus_set_filter(&cdnet->cdbus, filter);
}

/**
 * @brief 处理CDBUS帧数据
 * @param cdnet CDNET实例指针
 * @param frame CDBUS帧数据指针
 * @return 处理结果：0成功，-1失败
 * @details 解析CDBUS帧数据，根据协议类型提取CDNET数据包
 *          支持Layer 0（8位端口）和Layer 1（16位端口）两种协议格式
 */
int cdnet_process_frame(cdnet_t *cdnet, cdbus_frame_t *frame) {
    if (frame->data_len < 1) {
        return -1;  // 无效帧
    }
    
    cdnet_packet_t *packet = &cdnet->rx_packet;
    
    packet->src_addr = frame->src_addr;
    packet->dst_addr = frame->dst_addr;
    
    if (frame->data[0] == CDNET_TYPE_L0) {
        // Layer 0: 8位端口
        if (frame->data_len < 2) {
            return -1;
        }
        
        packet->type = CDNET_TYPE_L0;
        packet->frame.l0.port = frame->data[1];
        packet->frame.l0.data_len = frame->data_len - 2;
        
        if (packet->frame.l0.data_len > 0) {
            memcpy(packet->frame.l0.data, &frame->data[2], packet->frame.l0.data_len);
        }
    } else if (frame->data[0] == CDNET_TYPE_L1) {
        // Layer 1: 16位端口
        if (frame->data_len < 3) {
            return -1;
        }
        
        packet->type = CDNET_TYPE_L1;
        packet->frame.l1.port = (frame->data[1] << 8) | frame->data[2];
        packet->frame.l1.data_len = frame->data_len - 3;
        
        if (packet->frame.l1.data_len > 0) {
            memcpy(packet->frame.l1.data, &frame->data[3], packet->frame.l1.data_len);
        }
    } else {
        return -1;  // 未知帧类型
    }
    
    return 0;
}

/**
 * @brief 获取接收到的CDNET数据包
 * @param cdnet CDNET实例指针
 * @param packet 用于存储数据包的缓冲区
 * @return 获取结果：0成功
 */
int cdnet_get_packet(cdnet_t *cdnet, cdnet_packet_t *packet) {
    memcpy(packet, &cdnet->rx_packet, sizeof(cdnet_packet_t));
    return 0;
}

/**
 * @brief 创建Layer 0协议帧
 * @param port 8位端口号
 * @param data 用户数据缓冲区指针
 * @param len 用户数据长度
 * @param buffer 用于存储完整帧的缓冲区
 * @return 帧长度（字节数），-1表示失败
 * @details Layer 0帧格式：[类型(1字节)][端口(1字节)][数据(n字节)]
 */
int cdnet_create_l0_frame(uint8_t port, uint8_t *data, uint8_t len, uint8_t *buffer) {
    if (len > CDNET_MAX_DATA_SIZE - 2) {
        return -1;
    }
    
    buffer[0] = CDNET_TYPE_L0;
    buffer[1] = port;
    
    if (len > 0 && data != NULL) {
        memcpy(&buffer[2], data, len);
    }
    
    return len + 2;
}

/**
 * @brief 创建Layer 1协议帧
 * @param port 16位端口号
 * @param data 用户数据缓冲区指针
 * @param len 用户数据长度
 * @param buffer 用于存储完整帧的缓冲区
 * @return 帧长度（字节数），-1表示失败
 * @details Layer 1帧格式：[类型(1字节)][端口高字节][端口低字节][数据(n字节)]
 */
int cdnet_create_l1_frame(uint16_t port, uint8_t *data, uint8_t len, uint8_t *buffer) {
    if (len > CDNET_MAX_DATA_SIZE - 3) {
        return -1;
    }
    
    buffer[0] = CDNET_TYPE_L1;
    buffer[1] = (port >> 8) & 0xFF;
    buffer[2] = port & 0xFF;
    
    if (len > 0 && data != NULL) {
        memcpy(&buffer[3], data, len);
    }
    
    return len + 3;
}

/**
 * @brief 发送Layer 0数据包
 * @param cdnet CDNET实例指针
 * @param dst 目标节点地址
 * @param port 8位端口号
 * @param data 用户数据缓冲区指针
 * @param len 用户数据长度
 * @return 生成的CDBUS帧长度（字节数），-1表示失败
 * @details 通过CDBUS协议发送Layer 0格式的数据包
 */
int cdnet_send_l0(cdnet_t *cdnet, uint8_t dst, uint8_t port, uint8_t *data, uint8_t len) {
    uint8_t temp_buffer[CDNET_MAX_PACKET_SIZE];
    int frame_len = cdnet_create_l0_frame(port, data, len, temp_buffer);
    
    if (frame_len < 0) {
        return -1;
    }
    
    return cdbus_create_frame(cdnet->cdbus.address, dst, temp_buffer, frame_len, 
                             cdnet->tx_buffer);
}

/**
 * @brief 发送Layer 1数据包
 * @param cdnet CDNET实例指针
 * @param dst 目标节点地址
 * @param port 16位端口号
 * @param data 用户数据缓冲区指针
 * @param len 用户数据长度
 * @return 生成的CDBUS帧长度（字节数），-1表示失败
 * @details 通过CDBUS协议发送Layer 1格式的数据包
 */
int cdnet_send_l1(cdnet_t *cdnet, uint8_t dst, uint16_t port, uint8_t *data, uint8_t len) {
    uint8_t temp_buffer[CDNET_MAX_PACKET_SIZE];
    int frame_len = cdnet_create_l1_frame(port, data, len, temp_buffer);
    
    if (frame_len < 0) {
        return -1;
    }
    
    return cdbus_create_frame(cdnet->cdbus.address, dst, temp_buffer, frame_len, 
                             cdnet->tx_buffer);
}